/*
 * Copyright 2017 Baiyyy
 * @(#)HexUtils.java
 */

package com.byyy.ccts.core.utils;

import com.byyy.ccts.modules.cc.Global;
import com.byyy.ccts.modules.cc.entity.istr.InstructionMdl;
import com.byyy.ccts.modules.cc.entity.istr.TempAlarmMdl;

import java.util.Calendar;

/**
 * 指令处理工具类
 * Created by DELL on 2018-4-24.
 */
public class InstructionUtils {

    /** 流水号 */
    private static int SEQUENCE_NUM = 0;

    /**
     * 生成流水号
     *
     * @return
     */
    public synchronized static byte[] generateSequenceNum() {
        // 超过255重置
        if (SEQUENCE_NUM > 255) {
            SEQUENCE_NUM = 0;
        }

        Calendar now = Calendar.getInstance();
        byte[] num = new byte[] {
                (byte) (int) (Integer.valueOf(String.valueOf(now.get(Calendar.YEAR)).substring(2, 4)))
                , (byte) (now.get(Calendar.MONTH) + 1)
                , (byte) now.get(Calendar.DAY_OF_MONTH)
                , (byte) now.get(Calendar.HOUR_OF_DAY)
                , (byte) now.get(Calendar.MINUTE)
                , (byte) now.get(Calendar.SECOND)
                , (byte) SEQUENCE_NUM
        };
        SEQUENCE_NUM++;
        return num;
    }

    /**
     * 生成服务器平台响应消息
     * @return
     */
    public static byte[] generateCommResponse(InstructionMdl instruction, byte cmd) {
        // 生成流水号
        byte[] deviceId = instruction.getDeviceId();
        byte[] sequenceNum = generateSequenceNum();
        byte[] responseNum = instruction.getSequenceNum();

        // 生成应答消息
        byte[] res = new byte[]{
                Global.PACK_START, Global.ISTR_SERVER_RESPONSE
                , deviceId[0], deviceId[1], deviceId[2], deviceId[3], deviceId[4], deviceId[5]
                , sequenceNum[0], sequenceNum[1], sequenceNum[2], sequenceNum[3], sequenceNum[4], sequenceNum[5], sequenceNum[6]
                , responseNum[0], responseNum[1], responseNum[2], responseNum[3], responseNum[4], responseNum[5], responseNum[6]
                , cmd, 0x00, 0x00, Global.PACK_END
        };

        // 生成校验码
        return check(res);
    }

    /**
     * 生成设备操作指令
     * @return
     */
    public static byte[] generateDeviceOptCmd(InstructionMdl istrMdl, byte cmd, String param) {
        switch (cmd) {
            case Global.DEVICE_OTP_0X62:
                return generate0x62(istrMdl, param);
            case Global.DEVICE_OTP_0X64:
                return generate0x64(istrMdl, param);
            case Global.DEVICE_OTP_0X73:
                return generate0x73(istrMdl, param);
            case Global.DEVICE_OTP_0X78:
                return generate0x78(istrMdl, param);
            default:
                break;
        }

        return null;
    }

    /**
     * 将应答进行校验码生成操作
     * @param instruction
     * @return
     */
    public static byte[] check(byte[] instruction) {
        // 生成校验码
        byte check = 0x00;
        for (int i = 0; i < instruction.length - 2; i++) {
            check ^= instruction[i];
        }
        instruction[instruction.length - 2] = check;
        return instruction;
    }

    /**
     * 生成设备操作指令-设置报位间隔 0x62
     * @return
     */
    private static byte[] generate0x62(InstructionMdl istrMdl, String param) {
        byte[] content = HexUtils.int2bytes(Integer.valueOf(param) * 60 / 15);
        byte[] deviceId = istrMdl.getDeviceId();
        byte[] sequenceNum = generateSequenceNum();
        byte[] ret = new byte[]{
                Global.PACK_START, Global.DEVICE_OTP_0X62
                , deviceId[0], deviceId[1], deviceId[2], deviceId[3], deviceId[4], deviceId[5]
                , sequenceNum[0], sequenceNum[1], sequenceNum[2], sequenceNum[3], sequenceNum[4], sequenceNum[5], sequenceNum[6]
                , content[3], 0x00, Global.PACK_END
        };
        return check(ret);
    }

    /**
     * 生成设备操作指令-温度湿度光感预警报警总开关 0x73
     * @return
     */
    private static byte[] generate0x73(InstructionMdl istrMdl, String param) {
        byte[] deviceId = istrMdl.getDeviceId();
        byte[] sequenceNum = generateSequenceNum();
        byte[] ret = new byte[] {
                Global.PACK_START, Global.DEVICE_OTP_0X73
                , deviceId[0], deviceId[1], deviceId[2], deviceId[3], deviceId[4], deviceId[5]
                , sequenceNum[0], sequenceNum[1], sequenceNum[2], sequenceNum[3], sequenceNum[4], sequenceNum[5], sequenceNum[6]
                , 0x01
                , 0x00, Global.PACK_END
        };
        return check(ret);
    }

    /**
     * 生成设备操作指令-设定温度报警 0x64
     * @return
     */
    private static byte[] generate0x64(InstructionMdl istrMdl, String param) {
        String[] temps = param.split(",");
        byte[] deviceId = istrMdl.getDeviceId();
        byte[] sequenceNum = generateSequenceNum();
        TempAlarmMdl model = new TempAlarmMdl();
        // 设置高温符号，高温报警符号以及高温值、高温预警值
        if (temps[0].startsWith("-")) {
            model.setTempSymbolH(Global.OTH_TEMP_SYMBOL_MINUS);
            model.setTempWarningSymbolH(Global.OTH_TEMP_SYMBOL_MINUS);
        }
        else {
            model.setTempSymbolH(Global.OTH_TEMP_SYMBOL_PLUS);
            model.setTempWarningSymbolH(Global.OTH_TEMP_SYMBOL_PLUS);
        }
        model.setTempValueH((byte) Math.abs(Integer.valueOf(temps[0])));
        model.setTempWarningValueH((byte) Math.abs(Integer.valueOf(temps[0])));

        // 设置低温符号，低温报警符号以及低温值、低温预警值
        if (temps[1].startsWith("-")) {
            model.setTempSymbolL(Global.OTH_TEMP_SYMBOL_MINUS);
            model.setTempWarningSymbolL(Global.OTH_TEMP_SYMBOL_MINUS);
        }
        else {
            model.setTempSymbolL(Global.OTH_TEMP_SYMBOL_PLUS);
            model.setTempWarningSymbolL(Global.OTH_TEMP_SYMBOL_PLUS);
        }
        model.setTempValueL((byte) Math.abs(Integer.valueOf(temps[1])));
        model.setTempWarningValueL((byte) Math.abs(Integer.valueOf(temps[1])));

        byte[] ret = new byte[] {
                Global.PACK_START, Global.DEVICE_OTP_0X64
                , deviceId[0], deviceId[1], deviceId[2], deviceId[3], deviceId[4], deviceId[5]
                , sequenceNum[0], sequenceNum[1], sequenceNum[2], sequenceNum[3], sequenceNum[4], sequenceNum[5], sequenceNum[6]
                , model.getTempSymbolH(), model.getTempValueH()
                , model.getTempSymbolL(), model.getTempValueL()
                , model.getTempWarningValueH(), model.getTempWarningValueH()
                , model.getTempWarningSymbolL(), model.getTempWarningValueL()
                , Global.DEVICE_OTP_64_STARTTIME[0], Global.DEVICE_OTP_64_STARTTIME[1], Global.DEVICE_OTP_64_STARTTIME[2]
                , Global.DEVICE_OTP_64_STARTTIME[3], Global.DEVICE_OTP_64_STARTTIME[4], Global.DEVICE_OTP_64_STARTTIME[5]
                , Global.DEVICE_OTP_64_ENDTIME[0], Global.DEVICE_OTP_64_ENDTIME[1], Global.DEVICE_OTP_64_ENDTIME[2]
                , Global.DEVICE_OTP_64_ENDTIME[3], Global.DEVICE_OTP_64_ENDTIME[4], Global.DEVICE_OTP_64_ENDTIME[5]
                , 0x00, Global.PACK_END
        };
        return check(ret);
    }

    /**
     * 生成设备操作指令-设置报位间隔 0x62
     * @return
     */
    private static byte[] generate0x78(InstructionMdl istrMdl, String param) {
        byte[] content = HexUtils.int2bytes(Integer.valueOf(param) * 60 / 15);
        byte[] deviceId = istrMdl.getDeviceId();
        byte[] sequenceNum = generateSequenceNum();
        byte[] ret = new byte[]{
                Global.PACK_START, Global.DEVICE_OTP_0X78
                , deviceId[0], deviceId[1], deviceId[2], deviceId[3], deviceId[4], deviceId[5]
                , sequenceNum[0], sequenceNum[1], sequenceNum[2], sequenceNum[3], sequenceNum[4], sequenceNum[5], sequenceNum[6]
                , content[3], 0x00, Global.PACK_END
        };
        return check(ret);
    }

    public static void main(String[] args) {
        byte[] ret = generateSequenceNum();
        for (int i = 0; i < ret.length; i++) {
            System.out.printf("0x%02x", ret[i]);
        }
    }

}
